home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / ddx / mfb / RCS / mfbbitblt.c,v < prev    next >
Encoding:
Text File  |  1991-02-28  |  28.8 KB  |  1,163 lines

  1. head     1.2;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.2
  10. date     91.02.27.23.08.42;  author kupfer;  state Exp;
  11. branches ;
  12. next     1.1;
  13.  
  14. 1.1
  15. date     90.02.14.19.57.54;  author tve;  state Exp;
  16. branches ;
  17. next     ;
  18.  
  19.  
  20. desc
  21. @Original X11R4 distribution
  22. @
  23.  
  24.  
  25. 1.2
  26. log
  27. @MIT patch #3.
  28. @
  29. text
  30. @/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */
  31. /***********************************************************
  32. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
  33. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  34.  
  35.                         All Rights Reserved
  36.  
  37. Permission to use, copy, modify, and distribute this software and its 
  38. documentation for any purpose and without fee is hereby granted, 
  39. provided that the above copyright notice appear in all copies and that
  40. both that copyright notice and this permission notice appear in 
  41. supporting documentation, and that the names of Digital or MIT not be
  42. used in advertising or publicity pertaining to distribution of the
  43. software without specific, written prior permission.  
  44.  
  45. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  46. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  47. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  48. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  49. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  50. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  51. SOFTWARE.
  52.  
  53. ******************************************************************/
  54. /* $XConsortium: mfbbitblt.c,v 5.14 90/02/08 13:29:24 rws Exp $ */
  55. #include "X.h"
  56. #include "Xprotostr.h"
  57.  
  58. #include "miscstruct.h"
  59. #include "regionstr.h"
  60. #include "gcstruct.h"
  61. #include "windowstr.h"
  62. #include "pixmapstr.h"
  63. #include "scrnintstr.h"
  64.  
  65. #include "mi.h"
  66.  
  67. #include "mfb.h"
  68. #include "maskbits.h"
  69.  
  70.  
  71. /* CopyArea and CopyPlane for a monchrome frame buffer
  72.  
  73.  
  74.     clip the source rectangle to the source's available bits.  (this
  75. avoids copying unnecessary pieces that will just get exposed anyway.)
  76. this becomes the new shape of the destination.
  77.     clip the destination region to the composite clip in the
  78. GC.  this requires translating the destination region to (dstx, dsty).
  79.     build a list of source points, one for each rectangle in the
  80. destination.  this is a simple translation.
  81.     go do the multiple rectangle copies
  82.     do graphics exposures
  83. */
  84. /** Optimized for drawing pixmaps into windows, especially when drawing into
  85.  ** unobscured windows.  Calls to the general-purpose region code were
  86.  ** replaced with rectangle-to-rectangle clipping comparisions.  This is
  87.  ** possible, since the pixmap is a single rectangle.  In an unobscured
  88.  ** window, the destination clip is also a single rectangle, and region
  89.  ** code can be avoided entirely.  This is a big savings, since the region
  90.  ** code uses XAlloc() and makes many function calls.
  91.  **
  92.  ** In addition, if source is a pixmap, there is no need to call the
  93.  ** expensive miHandleExposures() routine.  Instead, we simply return NULL.
  94.  **
  95.  ** Previously, drawing a pixmap into an unobscured window executed at least
  96.  ** 8 XAlloc()'s, 30 function calls, and hundreds of lines of code.
  97.  **
  98.  ** Now, the same operation requires no XAlloc()'s, no region function calls,
  99.  ** and much less overhead.  Nice for drawing lots of small pixmaps.
  100.  */
  101.  
  102. RegionPtr
  103. mfbCopyArea(pSrcDrawable, pDstDrawable,
  104.         pGC, srcx, srcy, width, height, dstx, dsty)
  105. register DrawablePtr pSrcDrawable;
  106. register DrawablePtr pDstDrawable;
  107. register GC *pGC;
  108. int srcx, srcy;
  109. int width, height;
  110. int dstx, dsty;
  111. {
  112.     RegionPtr prgnSrcClip;    /* may be a new region, or just a copy */
  113.     Bool freeSrcClip = FALSE;
  114.  
  115.     RegionPtr prgnExposed;
  116.     RegionRec rgnDst;
  117.     DDXPointPtr pptSrc;
  118.     register DDXPointPtr ppt;
  119.     register BoxPtr pbox;
  120.     int i;
  121.     register int dx;
  122.     register int dy;
  123.     xRectangle origSource;
  124.     DDXPointRec origDest;
  125.     int numRects;
  126.     BoxRec fastBox;
  127.     int fastClip = 0;        /* for fast clipping with pixmap source */
  128.     int fastExpose = 0;        /* for fast exposures with pixmap source */
  129.  
  130.     origSource.x = srcx;
  131.     origSource.y = srcy;
  132.     origSource.width = width;
  133.     origSource.height = height;
  134.     origDest.x = dstx;
  135.     origDest.y = dsty;
  136.  
  137.     if ((pSrcDrawable != pDstDrawable) &&
  138.     pSrcDrawable->pScreen->SourceValidate)
  139.     (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, srcx, srcy, width, height);
  140.  
  141.     srcx += pSrcDrawable->x;
  142.     srcy += pSrcDrawable->y;
  143.  
  144.     /* clip the source */
  145.  
  146.     if (pSrcDrawable->type == DRAWABLE_PIXMAP)
  147.     {
  148.     if ((pSrcDrawable == pDstDrawable) &&
  149.         (pGC->clientClipType == CT_NONE))
  150.     {
  151.         prgnSrcClip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip;
  152.     }
  153.     else
  154.     {
  155.         /* Pixmap sources generate simple exposure events */
  156.         fastExpose = 1;
  157.  
  158.         /* Pixmap is just one clipping rectangle so we can avoid
  159.            allocating a full-blown region. */
  160.         fastClip = 1;
  161.  
  162.         fastBox.x1 = srcx;
  163.         fastBox.y1 = srcy;
  164.         fastBox.x2 = srcx + width;
  165.         fastBox.y2 = srcy + height;
  166.         
  167.         /* Left and top are already clipped, so clip right and bottom */
  168.         if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width)
  169.           fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
  170.         if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height)
  171.           fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
  172.     }
  173.     }
  174.     else
  175.     {
  176.     if (pGC->subWindowMode == IncludeInferiors)
  177.     {
  178.         if ((pSrcDrawable == pDstDrawable) &&
  179.         (pGC->clientClipType == CT_NONE))
  180.         {
  181.         prgnSrcClip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip;
  182.         }
  183.         else
  184.         {
  185.         prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable);
  186.         freeSrcClip = TRUE;
  187.         }
  188.     }
  189.     else
  190.     {
  191.         prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
  192.     }
  193.     }
  194.  
  195.     /* Don't create a source region if we are doing a fast clip */
  196.     if (!fastClip)
  197.     {
  198.     BoxRec srcBox;
  199.  
  200.     srcBox.x1 = srcx;
  201.     srcBox.y1 = srcy;
  202.     srcBox.x2 = srcx + width;
  203.     srcBox.y2 = srcy + height;
  204.     
  205.     (*pGC->pScreen->RegionInit)(&rgnDst, &srcBox, 1);
  206.     (*pGC->pScreen->Intersect)(&rgnDst, &rgnDst, prgnSrcClip);
  207.     }
  208.     
  209.     dstx += pDstDrawable->x;
  210.     dsty += pDstDrawable->y;
  211.  
  212.     if (pDstDrawable->type == DRAWABLE_WINDOW)
  213.     {
  214.     if (!((WindowPtr)pDstDrawable)->realized)
  215.     {
  216.         if (!fastClip)
  217.         (*pGC->pScreen->RegionUninit)(&rgnDst);
  218.         if (freeSrcClip)
  219.         (*pGC->pScreen->RegionDestroy)(prgnSrcClip);
  220.         return NULL;
  221.     }
  222.     }
  223.  
  224.     dx = srcx - dstx;
  225.     dy = srcy - dsty;
  226.  
  227.     /* Translate and clip the dst to the destination composite clip */
  228.     if (fastClip)
  229.     {
  230.     RegionPtr cclip;
  231.  
  232.         /* Translate the region directly */
  233.         fastBox.x1 -= dx;
  234.         fastBox.x2 -= dx;
  235.         fastBox.y1 -= dy;
  236.         fastBox.y2 -= dy;
  237.  
  238.     /* If the destination composite clip is one rectangle we can
  239.        do the clip directly.  Otherwise we have to create a full
  240.        blown region and call intersect */
  241.     cclip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip;
  242.         if (REGION_NUM_RECTS(cclip) == 1)
  243.         {
  244.         BoxPtr pBox = REGION_RECTS(cclip);
  245.       
  246.         if (fastBox.x1 < pBox->x1) fastBox.x1 = pBox->x1;
  247.         if (fastBox.x2 > pBox->x2) fastBox.x2 = pBox->x2;
  248.         if (fastBox.y1 < pBox->y1) fastBox.y1 = pBox->y1;
  249.         if (fastBox.y2 > pBox->y2) fastBox.y2 = pBox->y2;
  250.  
  251.         /* Check to see if the region is empty */
  252.         if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2)
  253.         (*pGC->pScreen->RegionInit)(&rgnDst, NullBox, 0);
  254.         else
  255.         (*pGC->pScreen->RegionInit)(&rgnDst, &fastBox, 1);
  256.     }
  257.         else
  258.     {
  259.         /* We must turn off fastClip now, since we must create
  260.            a full blown region.  It is intersected with the
  261.            composite clip below. */
  262.         fastClip = 0;
  263.         (*pGC->pScreen->RegionInit)(&rgnDst, &fastBox,1);
  264.     }
  265.     }
  266.     else
  267.     {
  268.         (*pGC->pScreen->TranslateRegion)(&rgnDst, -dx, -dy);
  269.     }
  270.  
  271.     if (!fastClip)
  272.     {
  273.     (*pGC->pScreen->Intersect)(&rgnDst,
  274.                    &rgnDst,
  275.                  ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip);
  276.     }
  277.  
  278.     /* Do bit blitting */
  279.     numRects = REGION_NUM_RECTS(&rgnDst);
  280.     if (numRects)
  281.     {
  282.     if(!(pptSrc = (DDXPointPtr)ALLOCATE_LOCAL(numRects *
  283.                           sizeof(DDXPointRec))))
  284.     {
  285.         (*pGC->pScreen->RegionUninit)(&rgnDst);
  286.         if (freeSrcClip)
  287.         (*pGC->pScreen->RegionDestroy)(prgnSrcClip);
  288.         return NULL;
  289.     }
  290.     pbox = REGION_RECTS(&rgnDst);
  291.     ppt = pptSrc;
  292.     for (i = numRects; --i >= 0; pbox++, ppt++)
  293.     {
  294.         ppt->x = pbox->x1 + dx;
  295.         ppt->y = pbox->y1 + dy;
  296.     }
  297.     
  298.     if (pGC->planemask & 1)
  299.         mfbDoBitblt(pSrcDrawable, pDstDrawable, pGC->alu, &rgnDst, pptSrc);
  300.     DEALLOCATE_LOCAL(pptSrc);
  301.     }
  302.  
  303.     prgnExposed = NULL;
  304.     if (((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->fExpose) {
  305.         /* Pixmap sources generate a NoExposed (we return NULL to do this) */
  306.         if (!fastExpose)
  307.         prgnExposed =
  308.         miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
  309.                   origSource.x, origSource.y,
  310.                   (int)origSource.width,
  311.                   (int)origSource.height,
  312.                   origDest.x, origDest.y, (unsigned long)0);
  313.     }
  314.     (*pGC->pScreen->RegionUninit)(&rgnDst);
  315.     if (freeSrcClip)
  316.     (*pGC->pScreen->RegionDestroy)(prgnSrcClip);
  317.     return prgnExposed;
  318. }
  319.  
  320. /* DoBitblt() does multiple rectangle moves into the rectangles
  321.    DISCLAIMER:
  322.    this code can be made much faster; this implementation is
  323. designed to be independent of byte/bit order, processor
  324. instruction set, and the like.  it could probably be done
  325. in a similarly device independent way using mask tables instead
  326. of the getbits/putbits macros.  the narrow case (w<32) can be
  327. subdivided into a case that crosses word boundaries and one that
  328. doesn't.
  329.  
  330.    we have to cope with the dircetion on a per band basis,
  331. rather than a per rectangle basis.  moving bottom to top
  332. means we have to invert the order of the bands; moving right
  333. to left requires reversing the order of the rectangles in
  334. each band.
  335.  
  336.    if src or dst is a window, the points have already been
  337. translated.
  338. */
  339.  
  340. #ifdef FASTGETBITS
  341. #define getunalignedword(psrc, x, dst) { \
  342.     register int _tmp; \
  343.     FASTGETBITS(psrc, x, 32, _tmp); \
  344.     dst = _tmp; \
  345. }
  346. #else
  347. #define getunalignedword(psrc, x, dst) \
  348. { \
  349.     dst = (SCRLEFT((unsigned) *(psrc), (x))) | \
  350.       (SCRRIGHT((unsigned) *((psrc)+1), 32-(x))); \
  351. }
  352. #endif  /* FASTGETBITS */
  353.  
  354. #include "fastblt.h"
  355.  
  356. mfbDoBitblt(pSrcDrawable, pDstDrawable, alu, prgnDst, pptSrc)
  357. DrawablePtr pSrcDrawable;
  358. DrawablePtr pDstDrawable;
  359. unsigned char alu;
  360. RegionPtr prgnDst;
  361. DDXPointPtr pptSrc;
  362. {
  363.     unsigned int *psrcBase, *pdstBase;    
  364.                 /* start of src and dst bitmaps */
  365.     int widthSrc, widthDst;    /* add to get to same position in next line */
  366.  
  367.     register BoxPtr pbox;
  368.     int nbox;
  369.  
  370.     BoxPtr pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2;
  371.                 /* temporaries for shuffling rectangles */
  372.     DDXPointPtr pptTmp, pptNew1, pptNew2;
  373.                 /* shuffling boxes entails shuffling the
  374.                    source points too */
  375.     int w, h;
  376.     int xdir;            /* 1 = left right, -1 = right left/ */
  377.     int ydir;            /* 1 = top down, -1 = bottom up */
  378.  
  379.     unsigned int *psrcLine, *pdstLine;    
  380.                 /* pointers to line with current src and dst */
  381.     register unsigned int *psrc;/* pointer to current src longword */
  382.     register unsigned int *pdst;/* pointer to current dst longword */
  383.  
  384.                 /* following used for looping through a line */
  385.     unsigned int startmask, endmask;    /* masks for writing ends of dst */
  386.     int nlMiddle;        /* whole longwords in dst */
  387.     register int nl;        /* temp copy of nlMiddle */
  388.     register unsigned int tmpSrc;
  389.                 /* place to store full source word */
  390.     register int xoffSrc;    /* offset (>= 0, < 32) from which to
  391.                        fetch whole longwords fetched 
  392.                    in src */
  393.     int nstart;            /* number of ragged bits at start of dst */
  394.     int nend;            /* number of ragged bits at end of dst */
  395.     int srcStartOver;        /* pulling nstart bits from src
  396.                    overflows into the next word? */
  397.     int careful;
  398.  
  399.  
  400.     if (pSrcDrawable->type == DRAWABLE_WINDOW)
  401.     {
  402.     psrcBase = (unsigned int *)
  403.         (((PixmapPtr)(pSrcDrawable->pScreen->devPrivate))->devPrivate.ptr);
  404.     widthSrc = (int)
  405.            ((PixmapPtr)(pSrcDrawable->pScreen->devPrivate))->devKind
  406.             >> 2;
  407.     }
  408.     else
  409.     {
  410.     psrcBase = (unsigned int *)(((PixmapPtr)pSrcDrawable)->devPrivate.ptr);
  411.     widthSrc = (int)(((PixmapPtr)pSrcDrawable)->devKind) >> 2;
  412.     }
  413.  
  414.     if (pDstDrawable->type == DRAWABLE_WINDOW)
  415.     {
  416.     pdstBase = (unsigned int *)
  417.         (((PixmapPtr)(pDstDrawable->pScreen->devPrivate))->devPrivate.ptr);
  418.     widthDst = (int)
  419.            ((PixmapPtr)(pDstDrawable->pScreen->devPrivate))->devKind
  420.             >> 2;
  421.     }
  422.     else
  423.     {
  424.     pdstBase = (unsigned int *)(((PixmapPtr)pDstDrawable)->devPrivate.ptr);
  425.     widthDst = (int)(((PixmapPtr)pDstDrawable)->devKind) >> 2;
  426.     }
  427.  
  428.     /* XXX we have to err on the side of safety when both are windows,
  429.      * because we don't know if IncludeInferiors is being used.
  430.      */
  431.     careful = ((pSrcDrawable == pDstDrawable) ||
  432.            ((pSrcDrawable->type == DRAWABLE_WINDOW) &&
  433.         (pDstDrawable->type == DRAWABLE_WINDOW)));
  434.  
  435.     pbox = REGION_RECTS(prgnDst);
  436.     nbox = REGION_NUM_RECTS(prgnDst);
  437.  
  438.     pboxNew1 = NULL;
  439.     pptNew1 = NULL;
  440.     pboxNew2 = NULL;
  441.     pptNew2 = NULL;
  442.     if (careful && (pptSrc->y < pbox->y1))
  443.     {
  444.         /* walk source botttom to top */
  445.     ydir = -1;
  446.     widthSrc = -widthSrc;
  447.     widthDst = -widthDst;
  448.  
  449.     if (nbox > 1)
  450.     {
  451.         /* keep ordering in each band, reverse order of bands */
  452.         pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
  453.         if(!pboxNew1)
  454.         return;
  455.         pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
  456.         if(!pptNew1)
  457.         {
  458.             DEALLOCATE_LOCAL(pboxNew1);
  459.             return;
  460.         }
  461.         pboxBase = pboxNext = pbox+nbox-1;
  462.         while (pboxBase >= pbox)
  463.         {
  464.             while ((pboxNext >= pbox) && 
  465.                (pboxBase->y1 == pboxNext->y1))
  466.             pboxNext--;
  467.             pboxTmp = pboxNext+1;
  468.             pptTmp = pptSrc + (pboxTmp - pbox);
  469.             while (pboxTmp <= pboxBase)
  470.             {
  471.             *pboxNew1++ = *pboxTmp++;
  472.             *pptNew1++ = *pptTmp++;
  473.             }
  474.             pboxBase = pboxNext;
  475.         }
  476.         pboxNew1 -= nbox;
  477.         pbox = pboxNew1;
  478.         pptNew1 -= nbox;
  479.         pptSrc = pptNew1;
  480.         }
  481.     }
  482.     else
  483.     {
  484.     /* walk source top to bottom */
  485.     ydir = 1;
  486.     }
  487.  
  488.     if (careful && (pptSrc->x < pbox->x1))
  489.     {
  490.     /* walk source right to left */
  491.         xdir = -1;
  492.  
  493.     if (nbox > 1)
  494.     {
  495.         /* reverse order of rects in each band */
  496.         pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
  497.         pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
  498.         if(!pboxNew2 || !pptNew2)
  499.         {
  500.         if (pptNew2) DEALLOCATE_LOCAL(pptNew2);
  501.         if (pboxNew2) DEALLOCATE_LOCAL(pboxNew2);
  502.         if (pboxNew1)
  503.         {
  504.             DEALLOCATE_LOCAL(pptNew1);
  505.             DEALLOCATE_LOCAL(pboxNew1);
  506.         }
  507.             return;
  508.         }
  509.         pboxBase = pboxNext = pbox;
  510.         while (pboxBase < pbox+nbox)
  511.         {
  512.             while ((pboxNext < pbox+nbox) &&
  513.                (pboxNext->y1 == pboxBase->y1))
  514.             pboxNext++;
  515.             pboxTmp = pboxNext;
  516.             pptTmp = pptSrc + (pboxTmp - pbox);
  517.             while (pboxTmp != pboxBase)
  518.             {
  519.             *pboxNew2++ = *--pboxTmp;
  520.             *pptNew2++ = *--pptTmp;
  521.             }
  522.             pboxBase = pboxNext;
  523.         }
  524.         pboxNew2 -= nbox;
  525.         pbox = pboxNew2;
  526.         pptNew2 -= nbox;
  527.         pptSrc = pptNew2;
  528.     }
  529.     }
  530.     else
  531.     {
  532.     /* walk source left to right */
  533.         xdir = 1;
  534.     }
  535.  
  536.  
  537.     /* special case copy */
  538.     if (alu == GXcopy)
  539.     {
  540.     register unsigned int bits;
  541.     register unsigned int bits1;
  542.     int xoffSrc, xoffDst;
  543.     int    leftShift, rightShift;
  544.  
  545.     while(nbox--)
  546.     {
  547.         w = pbox->x2 - pbox->x1;
  548.         h = pbox->y2 - pbox->y1;
  549.  
  550.         if (ydir == -1) /* start at last scanline of rectangle */
  551.         {
  552.             psrcLine = psrcBase + ((pptSrc->y+h-1) * -widthSrc);
  553.             pdstLine = pdstBase + ((pbox->y2-1) * -widthDst);
  554.         }
  555.         else /* start at first scanline */
  556.         {
  557.             psrcLine = psrcBase + (pptSrc->y * widthSrc);
  558.             pdstLine = pdstBase + (pbox->y1 * widthDst);
  559.         }
  560.         if ((pbox->x1 & 0x1f) + w <= 32)
  561.         {
  562.         pdst = pdstLine + (pbox->x1 >> 5);
  563.         psrc = psrcLine + (pptSrc->x >> 5);
  564.         xoffSrc = pptSrc->x & 0x1f;
  565.         xoffDst = pbox->x1 & 0x1f;
  566.         while (h--)
  567.         {
  568.             getandputbits(psrc, xoffSrc, xoffDst, w, pdst);
  569.             psrc += widthSrc;
  570.             pdst += widthDst;
  571.         }
  572.         }
  573.         else
  574.         {
  575.             maskbits(pbox->x1, w, startmask, endmask, nlMiddle);
  576.             if (xdir == 1)
  577.             {
  578.                 xoffSrc = pptSrc->x & 0x1f;
  579.                 xoffDst = pbox->x1 & 0x1f;
  580.             pdstLine += (pbox->x1 >> 5);
  581.             psrcLine += (pptSrc->x >> 5);
  582.             if (xoffSrc == xoffDst)
  583.             {
  584.                     while (h--)
  585.                     {
  586.                     psrc = psrcLine;
  587.                     pdst = pdstLine;
  588.                     pdstLine += widthDst;
  589.                     psrcLine += widthSrc;
  590.                 if (startmask)
  591.                 {
  592.                     *pdst = (*pdst & ~startmask) | (*psrc++ & startmask);
  593.                     pdst++;
  594.                 }
  595.                 nl = nlMiddle;
  596.  
  597. #ifdef LARGE_INSTRUCTION_CACHE
  598. #ifdef FAST_CONSTANT_OFFSET_MODE
  599.  
  600.                 psrc += nl & (UNROLL-1);
  601.                 pdst += nl & (UNROLL-1);
  602.  
  603. #define BodyOdd(n) pdst[-n] = psrc[-n];
  604. #define BodyEven(n) pdst[-n] = psrc[-n];
  605.  
  606. #define LoopReset \
  607.     pdst += UNROLL; \
  608.     psrc += UNROLL;
  609.  
  610. #else
  611.  
  612. #define BodyOdd(n)  *pdst++ = *psrc++;
  613. #define BodyEven(n) BodyOdd(n)
  614.  
  615. #define LoopReset   ;
  616.  
  617. #endif
  618.                 PackedLoop
  619.  
  620. #undef BodyOdd
  621. #undef BodyEven
  622. #undef LoopReset
  623.  
  624. #else
  625.                 DuffL(nl, label1, *pdst++ = *psrc++;)
  626. #endif
  627.                 if (endmask)
  628.                     *pdst = (*pdst & ~endmask) | (*psrc++ & endmask);
  629.                 }
  630.             }
  631.             else
  632.             {
  633.                 if (xoffSrc > xoffDst)
  634.             {
  635.                 leftShift = (xoffSrc - xoffDst);
  636.                 rightShift = 32 - leftShift;
  637.             }
  638.                 else
  639.             {
  640.                 rightShift = (xoffDst - xoffSrc);
  641.                 leftShift = 32 - rightShift;
  642.             }
  643.                 while (h--)
  644.                 {
  645.                 psrc = psrcLine;
  646.                 pdst = pdstLine;
  647.                 pdstLine += widthDst;
  648.                 psrcLine += widthSrc;
  649.                 bits = 0;
  650.                 if (xoffSrc > xoffDst)
  651.                     bits = *psrc++;
  652.                 if (startmask)
  653.                 {
  654.                     bits1 = SCRLEFT(bits,leftShift);
  655.                     bits = *psrc++;
  656.                     bits1 |= SCRRIGHT(bits,rightShift);
  657.                     *pdst = (*pdst & ~startmask) |
  658.                         (bits1 & startmask);
  659.                     pdst++;
  660.                 }
  661.                 nl = nlMiddle;
  662.  
  663. #ifdef LARGE_INSTRUCTION_CACHE
  664.                 bits1 = bits;
  665. #ifdef FAST_CONSTANT_OFFSET_MODE
  666.  
  667.                 psrc += nl & (UNROLL-1);
  668.                 pdst += nl & (UNROLL-1);
  669.  
  670. #define BodyOdd(n) \
  671.     bits = psrc[-n]; \
  672.     pdst[-n] = BitLeft(bits1, leftShift) | BitRight(bits, rightShift);
  673.  
  674. #define BodyEven(n) \
  675.     bits1 = psrc[-n]; \
  676.     pdst[-n] = BitLeft(bits, leftShift) | BitRight(bits1, rightShift);
  677.  
  678. #define LoopReset \
  679.     pdst += UNROLL; \
  680.     psrc += UNROLL;
  681.  
  682. #else
  683.  
  684. #define BodyOdd(n) \
  685.     bits = *psrc++; \
  686.     *pdst++ = BitLeft(bits1, leftShift) | BitRight(bits, rightShift);
  687.                
  688. #define BodyEven(n) \
  689.     bits1 = *psrc++; \
  690.     *pdst++ = BitLeft(bits, leftShift) | BitRight(bits1, rightShift);
  691.  
  692. #define LoopReset   ;
  693.  
  694. #endif    /* !FAST_CONSTANT_OFFSET_MODE */
  695.  
  696.                 PackedLoop
  697.  
  698. #undef BodyOdd
  699. #undef BodyEven
  700. #undef LoopReset
  701.     
  702. #else
  703.                 DuffL (nl,label2,
  704.                 bits1 = BitLeft(bits, leftShift);
  705.                 bits = *psrc++;
  706.                 *pdst++ = bits1 | BitRight(bits, rightShift);
  707.                 )
  708. #endif
  709.                 if (endmask)
  710.                 {
  711.                     bits1 = SCRLEFT(bits, leftShift);
  712.                     if (SCRLEFT(endmask, rightShift))
  713.                     {
  714.                     bits = *psrc++;
  715.                     bits1 |= SCRRIGHT(bits, rightShift);
  716.                     }
  717.                     *pdst = (*pdst & ~endmask) |
  718.                         (bits1 & endmask);
  719.                 }
  720.                 }
  721.             }
  722.             }
  723.             else    /* xdir == -1 */
  724.             {
  725.                 xoffSrc = (pptSrc->x + w - 1) & 0x1f;
  726.                 xoffDst = (pbox->x2 - 1) & 0x1f;
  727.             pdstLine += ((pbox->x2-1) >> 5) + 1;
  728.             psrcLine += ((pptSrc->x+w - 1) >> 5) + 1;
  729.             if (xoffSrc == xoffDst)
  730.             {
  731.                     while (h--)
  732.                     {
  733.                     psrc = psrcLine;
  734.                     pdst = pdstLine;
  735.                     pdstLine += widthDst;
  736.                     psrcLine += widthSrc;
  737.                 if (endmask)
  738.                 {
  739.                     pdst--;
  740.                     *pdst = (*pdst & ~endmask) | (*--psrc & endmask);
  741.                 }
  742.                 nl = nlMiddle;
  743.  
  744. #ifdef LARGE_INSTRUCTION_CACHE
  745. #ifdef FAST_CONSTANT_OFFSET_MODE
  746.                 psrc -= nl & (UNROLL - 1);
  747.                 pdst -= nl & (UNROLL - 1);
  748.  
  749. #define BodyOdd(n) pdst[n-1] = psrc[n-1];
  750.  
  751. #define BodyEven(n) pdst[n-1] = psrc[n-1];
  752.  
  753. #define LoopReset \
  754.     pdst -= UNROLL;\
  755.     psrc -= UNROLL;
  756.  
  757. #else
  758.  
  759. #define BodyOdd(n)  *--pdst = *--psrc;
  760. #define BodyEven(n) BodyOdd(n)
  761. #define LoopReset   ;
  762.  
  763. #endif
  764.                 PackedLoop
  765.  
  766. #undef BodyOdd
  767. #undef BodyEven
  768. #undef LoopReset
  769.  
  770. #else
  771.                 DuffL(nl,label3, *--pdst = *--psrc;)
  772. #endif
  773.                 if (startmask)
  774.                 {
  775.                     --pdst;
  776.                     *pdst = (*pdst & ~startmask) | (*--psrc & startmask);
  777.                 }
  778.                 }
  779.             }
  780.             else
  781.             {
  782.             if (xoffDst > xoffSrc)
  783.             {
  784.                 rightShift = (xoffDst - xoffSrc);
  785.                 leftShift = 32 - rightShift;
  786.             }
  787.             else
  788.             {
  789.                     leftShift = (xoffSrc - xoffDst);
  790.                     rightShift = 32 - leftShift;
  791.             }
  792.                     while (h--)
  793.                     {
  794.                     psrc = psrcLine;
  795.                     pdst = pdstLine;
  796.                     pdstLine += widthDst;
  797.                     psrcLine += widthSrc;
  798.                 bits = 0;
  799.                 if (xoffDst > xoffSrc)
  800.                 bits = *--psrc;
  801.                 if (endmask)
  802.                 {
  803.                     bits1 = SCRRIGHT(bits, rightShift);
  804.                     bits = *--psrc;
  805.                     bits1 |= SCRLEFT(bits, leftShift);
  806.                     pdst--;
  807.                     *pdst = (*pdst & ~endmask) |
  808.                         (bits1 & endmask);
  809.                 }
  810.                 nl = nlMiddle;
  811.  
  812. #ifdef LARGE_INSTRUCTION_CACHE
  813.                 bits1 = bits;
  814. #ifdef FAST_CONSTANT_OFFSET_MODE
  815.                 psrc -= nl & (UNROLL - 1);
  816.                 pdst -= nl & (UNROLL - 1);
  817.  
  818. #define BodyOdd(n) \
  819.     bits = psrc[n-1]; \
  820.     pdst[n-1] = BitRight(bits1, rightShift) | BitLeft(bits, leftShift);
  821.  
  822. #define BodyEven(n) \
  823.     bits1 = psrc[n-1]; \
  824.     pdst[n-1] = BitRight(bits, rightShift) | BitLeft(bits1, leftShift);
  825.  
  826. #define LoopReset \
  827.     pdst -= UNROLL; \
  828.     psrc -= UNROLL;
  829.  
  830. #else
  831.  
  832. #define BodyOdd(n) \
  833.     bits = *--psrc; \
  834.     *--pdst = BitRight(bits1, rightShift) | BitLeft(bits, leftShift);
  835.  
  836. #define BodyEven(n) \
  837.     bits1 = *--psrc; \
  838.     *--pdst = BitRight(bits, rightShift) | BitLeft(bits1, leftShift);
  839.  
  840. #define LoopReset   ;
  841.  
  842. #endif
  843.  
  844.                 PackedLoop
  845.  
  846. #undef BodyOdd
  847. #undef BodyEven
  848. #undef LoopReset
  849.  
  850. #else
  851.                 DuffL (nl, label4,
  852.                 bits1 = BitRight(bits, rightShift);
  853.                 bits = *--psrc;
  854.                 *--pdst = bits1 | BitLeft(bits, leftShift);
  855.                 )
  856. #endif
  857.  
  858.                 if (startmask)
  859.                 {
  860.                     bits1 = SCRRIGHT(bits, rightShift);
  861.                     if (SCRRIGHT (startmask, leftShift))
  862.                     {
  863.                     bits = *--psrc;
  864.                     bits1 |= SCRLEFT(bits, leftShift);
  865.                     }
  866.                     --pdst;
  867.                     *pdst = (*pdst & ~startmask) |
  868.                         (bits1 & startmask);
  869.                 }
  870.                 }
  871.             }
  872.             }
  873.         }
  874.         pbox++;
  875.         pptSrc++;
  876.     }
  877.     }
  878.     else /* do some rop */
  879.     {
  880.         while (nbox--)
  881.         {
  882.         w = pbox->x2 - pbox->x1;
  883.         h = pbox->y2 - pbox->y1;
  884.  
  885.         if (ydir == -1) /* start at last scanline of rectangle */
  886.         {
  887.             psrcLine = psrcBase + ((pptSrc->y+h-1) * -widthSrc);
  888.             pdstLine = pdstBase + ((pbox->y2-1) * -widthDst);
  889.         }
  890.         else /* start at first scanline */
  891.         {
  892.             psrcLine = psrcBase + (pptSrc->y * widthSrc);
  893.             pdstLine = pdstBase + (pbox->y1 * widthDst);
  894.         }
  895.  
  896.         /* x direction doesn't matter for < 1 longword */
  897.         if (w <= 32)
  898.         {
  899.             int srcBit, dstBit;    /* bit offset of src and dst */
  900.  
  901.             pdstLine += (pbox->x1 >> 5);
  902.             psrcLine += (pptSrc->x >> 5);
  903.             psrc = psrcLine;
  904.             pdst = pdstLine;
  905.  
  906.             srcBit = pptSrc->x & 0x1f;
  907.             dstBit = pbox->x1 & 0x1f;
  908.  
  909.             while(h--)
  910.             {
  911.             getandputrop(psrc, srcBit, dstBit, w, pdst, alu)
  912.             pdst += widthDst;
  913.             psrc += widthSrc;
  914.             }
  915.         }
  916.         else
  917.         {
  918.             maskbits(pbox->x1, w, startmask, endmask, nlMiddle)
  919.             if (startmask)
  920.             nstart = 32 - (pbox->x1 & 0x1f);
  921.             else
  922.             nstart = 0;
  923.             if (endmask)
  924.                 nend = pbox->x2 & 0x1f;
  925.             else
  926.             nend = 0;
  927.  
  928.             xoffSrc = ((pptSrc->x & 0x1f) + nstart) & 0x1f;
  929.             srcStartOver = ((pptSrc->x & 0x1f) + nstart) > 31;
  930.  
  931.             if (xdir == 1) /* move left to right */
  932.             {
  933.                 pdstLine += (pbox->x1 >> 5);
  934.                 psrcLine += (pptSrc->x >> 5);
  935.  
  936.             while (h--)
  937.             {
  938.                 psrc = psrcLine;
  939.                 pdst = pdstLine;
  940.  
  941.                 if (startmask)
  942.                 {
  943.                 getandputrop(psrc, (pptSrc->x & 0x1f), 
  944.                      (pbox->x1 & 0x1f), nstart, pdst, alu)
  945.                 pdst++;
  946.                 if (srcStartOver)
  947.                     psrc++;
  948.                 }
  949.  
  950.             /* special case for aligned operations */
  951.             if (xoffSrc == 0)
  952.             {
  953.                 nl = nlMiddle;
  954.                 while (nl--)
  955.                 {
  956.                 DoRop (*pdst, alu, *psrc++, *pdst);
  957.                  pdst++;
  958.                 }
  959.             }
  960.              else
  961.             {
  962.                 nl = nlMiddle + 1;
  963.                 while (--nl)
  964.                     {
  965.                 getunalignedword (psrc, xoffSrc, tmpSrc)
  966.                 DoRop (*pdst, alu, tmpSrc, *pdst);
  967.                 pdst++;
  968.                 psrc++;
  969.                 }
  970.             }
  971.  
  972.                 if (endmask)
  973.                 {
  974.                 getandputrop0(psrc, xoffSrc, nend, pdst, alu);
  975.                 }
  976.  
  977.                 pdstLine += widthDst;
  978.                 psrcLine += widthSrc;
  979.             }
  980.             }
  981.             else /* move right to left */
  982.             {
  983.                 pdstLine += (pbox->x2 >> 5);
  984.                 psrcLine += (pptSrc->x+w >> 5);
  985.             /* if fetch of last partial bits from source crosses
  986.                a longword boundary, start at the previous longword
  987.             */
  988.             if (xoffSrc + nend >= 32)
  989.                 --psrcLine;
  990.  
  991.             while (h--)
  992.             {
  993.                 psrc = psrcLine;
  994.                 pdst = pdstLine;
  995.  
  996.                 if (endmask)
  997.                 {
  998.                 getandputrop0(psrc, xoffSrc, nend, pdst, alu);
  999.                 }
  1000.  
  1001.                 nl = nlMiddle + 1;
  1002.                 while (--nl)
  1003.                 {
  1004.                 --psrc;
  1005.                 --pdst;
  1006.                 getunalignedword(psrc, xoffSrc, tmpSrc)
  1007.                 DoRop(*pdst, alu, tmpSrc, *pdst);
  1008.                 }
  1009.  
  1010.                 if (startmask)
  1011.                 {
  1012.                 if (srcStartOver)
  1013.                     --psrc;
  1014.                 --pdst;
  1015.                 getandputrop(psrc, (pptSrc->x & 0x1f), 
  1016.                      (pbox->x1 & 0x1f), nstart, pdst, alu)
  1017.                 }
  1018.  
  1019.                 pdstLine += widthDst;
  1020.                 psrcLine += widthSrc;
  1021.             }
  1022.             } /* move right to left */
  1023.         }
  1024.         pbox++;
  1025.         pptSrc++;
  1026.         } /* while (nbox--) */
  1027.     }
  1028.  
  1029.     /* free up stuff */
  1030.     if (pboxNew2)
  1031.     {
  1032.     DEALLOCATE_LOCAL(pptNew2);
  1033.     DEALLOCATE_LOCAL(pboxNew2);
  1034.     }
  1035.     if (pboxNew1)
  1036.     {
  1037.     DEALLOCATE_LOCAL(pptNew1);
  1038.     DEALLOCATE_LOCAL(pboxNew1);
  1039.     }
  1040. }
  1041.  
  1042. /*
  1043.  * Allow devices which use mfb for 1-bit pixmap support
  1044.  * to register a function for n-to-1 copy operations, instead
  1045.  * of falling back to miCopyPlane
  1046.  */
  1047.  
  1048. static unsigned long    copyPlaneGeneration;
  1049. static int        copyPlaneScreenIndex = -1;
  1050.  
  1051. Bool
  1052. mfbRegisterCopyPlaneProc (pScreen, proc)
  1053.     ScreenPtr    pScreen;
  1054.     RegionPtr    (*proc)();
  1055. {
  1056.     if (copyPlaneGeneration != serverGeneration)
  1057.     {
  1058.     copyPlaneScreenIndex = AllocateScreenPrivateIndex();
  1059.     if (copyPlaneScreenIndex < 0)
  1060.         return FALSE;
  1061.     copyPlaneGeneration = serverGeneration;
  1062.     }
  1063.     pScreen->devPrivates[copyPlaneScreenIndex].ptr = (pointer) proc;
  1064.     return TRUE;
  1065. }
  1066.  
  1067. /*
  1068.     if fg == 1 and bg ==0, we can do an ordinary CopyArea.
  1069.     if fg == bg, we can do a CopyArea with alu = mfbReduceRop(alu, fg)
  1070.     if fg == 0 and bg == 1, we use the same rasterop, with
  1071.     source operand inverted.
  1072.  
  1073.     CopyArea deals with all of the graphics exposure events.
  1074.     This code depends on knowing that we can change the
  1075. alu in the GC without having to call ValidateGC() before calling
  1076. CopyArea().
  1077.  
  1078. */
  1079.  
  1080. RegionPtr
  1081. mfbCopyPlane(pSrcDrawable, pDstDrawable,
  1082.         pGC, srcx, srcy, width, height, dstx, dsty, plane)
  1083. DrawablePtr pSrcDrawable, pDstDrawable;
  1084. register GC *pGC;
  1085. int srcx, srcy;
  1086. int width, height;
  1087. int dstx, dsty;
  1088. unsigned long plane;
  1089. {
  1090.     int alu;
  1091.     RegionPtr    prgnExposed;
  1092.     RegionPtr    (*copyPlane)();
  1093.  
  1094.     if (pSrcDrawable->depth != 1)
  1095.     {
  1096.     if (copyPlaneScreenIndex >= 0 &&
  1097.         (copyPlane = (RegionPtr (*)()) 
  1098.         pSrcDrawable->pScreen->devPrivates[copyPlaneScreenIndex].ptr)
  1099.         )
  1100.     {
  1101.         return (*copyPlane) (pSrcDrawable, pDstDrawable,
  1102.                pGC, srcx, srcy, width, height, dstx, dsty, plane);
  1103.     }
  1104.     else
  1105.         return miCopyPlane(pSrcDrawable, pDstDrawable,
  1106.                pGC, srcx, srcy, width, height, dstx, dsty, plane);
  1107.     }
  1108.     if (plane != 1)
  1109.     return NULL;
  1110.  
  1111.     if ((pGC->fgPixel == 1) && (pGC->bgPixel == 0))
  1112.     {
  1113.     prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable,
  1114.              pGC, srcx, srcy, width, height, dstx, dsty);
  1115.     }
  1116.     else if (pGC->fgPixel == pGC->bgPixel)
  1117.     {
  1118.     alu = pGC->alu;
  1119.     pGC->alu = mfbReduceRop(pGC->alu, pGC->fgPixel);
  1120.     prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable,
  1121.              pGC, srcx, srcy, width, height, dstx, dsty);
  1122.     pGC->alu = alu;
  1123.     }
  1124.     else /* need to invert the src */
  1125.     {
  1126.     alu = pGC->alu;
  1127.     pGC->alu = InverseAlu[alu];
  1128.     prgnExposed = (*pGC->ops->CopyArea)(pSrcDrawable, pDstDrawable,
  1129.              pGC, srcx, srcy, width, height, dstx, dsty);
  1130.     pGC->alu = alu;
  1131.     }
  1132.     return prgnExposed;
  1133. }
  1134. @
  1135.  
  1136.  
  1137. 1.1
  1138. log
  1139. @Initial revision
  1140. @
  1141. text
  1142. @d25 1
  1143. a25 1
  1144. /* $XConsortium: mfbbitblt.c,v 5.13 89/11/30 15:32:17 keith Exp $ */
  1145. a83 1
  1146.     RegionRec rgnSrcRec;
  1147. d189 1
  1148. a189 3
  1149.         if (prgnSrcClip == &rgnSrcRec)
  1150.         (*pGC->pScreen->RegionUninit)(prgnSrcClip);
  1151.         else if (freeSrcClip)
  1152. d257 1
  1153. a257 3
  1154.         if (prgnSrcClip == &rgnSrcRec)
  1155.         (*pGC->pScreen->RegionUninit)(prgnSrcClip);
  1156.         else if (freeSrcClip)
  1157. d286 1
  1158. a286 3
  1159.     if (prgnSrcClip == &rgnSrcRec)
  1160.     (*pGC->pScreen->RegionUninit)(prgnSrcClip);
  1161.     else if (freeSrcClip)
  1162. @
  1163.